#include "Protocol.hpp"
#include "TcpServer.hpp"
#include "Deamon.hpp"
#include <memory>

using namespace ns_protocol;

Response Calculate(const Request &req) // 给一个请求，返回一个响应
{
    Response resp(req._x, req._y, req._op);
    switch (req._op)
    {
    case '+':
        resp._result = req._x + req._y;
        break;

    case '-':
        resp._result = req._x - req._y;
        break;

    case '*':
        resp._result = req._x * req._y;
        break;

    case '/':
        if (req._y == 0)
            resp._code = 1;
        else
            resp._result = req._x / req._y;
        break;

    case '%':
        if (req._y == 0)
            resp._code = 2;
        else
            resp._result = req._x % req._y;
        break;

    default:
        resp._code = 3;
        break;
    }
    return resp;
}

void NetCal(int sock)
{
    signal(SIGPIPE, SIG_IGN); // 忽略该信号，防止给客户端发消息时，客户端关闭
    string inbuffer;          // 一旦读到数据就放在这里
    while (true)
    {
        bool ret = Recv(sock, &inbuffer); // 读上来所有数据（追加）
        if (!ret)
            break; // 该连接已经断开（客户端退出）

        string reqString = Decode(inbuffer); // 根据报头，拆分出一个完整的请求报文
        if (reqString.empty())
            continue; // 没有完整报文，回去重读

        // 走到这里说明肯定有一个完整的请求报文了
        Request req;
        req.DeSerialized(reqString); // 反序列化设置进req

        Response resp = Calculate(req); // 经过计算得到resp

        string respString = resp.Serialize(); // 获得反序列化的响应字符串
        respString = Encode(respString);      // 添加报头，方便对端拆分
        Send(sock, respString);               // 发送回客户端
    }
}

void Usage(const char *proc)
{
    cout << "Usage: " << proc << " port" << endl;
}

// ./server ip port 启动服务器
int main(int argc, const char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }
    MyDeamon();                     // 守护进程化
    
    uint16_t port = atoi(argv[1]); // 获取命令行输入的port
    unique_ptr<TcpServer> tcpServer(new TcpServer(port));
    tcpServer->BindService(NetCal); // 先将服务准备好
    tcpServer->Start();             // 再开始获取连接

    return 0;
}